package drazing;

import java.awt.Shape;
import java.awt.geom.AffineTransform;
import java.awt.geom.PathIterator;
import java.awt.geom.Point2D;
import java.awt.geom.Rectangle2D;

/**
 * Detector de colisiones para el motor de física
 * @author xcubo
 */
public class CollisionDetector {

    private ControladorCarrera race_ctrl;

    public CollisionDetector(ControladorCarrera rc) {
        race_ctrl = rc;
    }

    /**
     * Devuelve la colisión de un coche
     * @param c Coche que colisiona
     * @return int Valor de la colisión (0 si no la hay)
     */
    public int collide(Car c) {
        // Coordenadas del coche y orientacion
        Point2D cn, fl, fr, bl, br;
        double x1 = c.getX();
        double y1 = c.getY();
        cn = new Point2D.Double(x1, y1);

        double rotation = c.getOrientacion() * Math.PI / 32.0;

        // Cojo la lista de obstaculos del circuito
        Pista trk = race_ctrl.getCircuit();
        Obstaculo[] obs = trk.getObstacles();

        // Calculo de posicion de los sensores
        Rectangle2D front, back;
        AffineTransform at = new AffineTransform();
        front = new Rectangle2D.Double(x1 - 7, y1, 14, 4);
        back = new Rectangle2D.Double(x1 - 8, y1 + 20, 16, 5);
        at.setToRotation(rotation, x1, y1 + 12);
        float coord[] = new float[5];
        PathIterator p;

        p = front.getPathIterator(at);
        p.currentSegment(coord);

        fl = new Point2D.Float(coord[0], coord[1]);
        p.next();
        p.currentSegment(coord);
        fr = new Point2D.Float(coord[0], coord[1]);
        p.next();
        p.currentSegment(coord);
        br = new Point2D.Float(coord[0], coord[1]);
        p.next();
        p.currentSegment(coord);
        bl = new Point2D.Float(coord[0], coord[1]);

        // Comprobamos todos los obstaculos del circuito por si impacta en alguno
        for (int i = 0; i < trk.getNumObs(); i++) {
            Obstaculo o = obs[i];
            Shape cuerpo = o.getSahpe();
            // COMPROBAR QUE EL OBSTACULO NO ES DE TIPO 0
            if (cuerpo.contains(fl) || cuerpo.contains(fr) || cuerpo.contains(br) || cuerpo.contains(bl)) {
                return 1;
            }
        }
        return 0;
    }

    /**
     * Devuelve si se ha pasado por meta
     * @param c Coche
     * @return Si o no
     */
    public boolean hasFinished(Car c)
    {
        double x = c.getX();
        double y = c.getY();

        Pista p = race_ctrl.getCircuit();
        if (p.getEndLine().contains(x, y))
            return true;
        else
            return false;
    }

    /**
     * Devuelve si se ha salido del circuito
     * @param c Coche
     * @param wheel Vector de ruedas
     */
    public void offRoad(Car c, boolean wheel[])
    {
        double x = c.getX();
        double y = c.getY();
        double rotation = c.getOrientacion() * Math.PI / 32.0;

        Rectangle2D lfw, rfw, lbw, rbw;
        AffineTransform at = new AffineTransform();

        lfw = new Rectangle2D.Double(x - 8, y + 5, 5, 6);        // Reducimos en 2 las ruedas por los arcenes
        rfw = new Rectangle2D.Double(x + 7, y + 5, 5, 6);         // Antes estaban en (-10,3) y1 (5,3)
        lbw = new Rectangle2D.Double(x - 8, y + 18, 5, 6);
        rbw = new Rectangle2D.Double(x + 7, y + 18, 5, 6);

        at.setToRotation(rotation, x, y + 12);

        Pista t = race_ctrl.getCircuit();
        float coord[] = new float[5];
        PathIterator p;

        // Comprobamos rueda delantera izquierda
        p = lfw.getPathIterator(at);
        p.currentSegment(coord);

        x = coord[0];
        y = coord[1];

        if (t.getSurface(0).contains(x, y)) {
            wheel[0] = true;
        }

        //Comprobamos rueda delantera derecha
        p = rfw.getPathIterator(at);
        p.currentSegment(coord);

        x = coord[0];
        y = coord[1];

        if (t.getSurface(0).contains(x, y)) {
            wheel[1] = true;
        }


        // Comprobamos rueda trasera izquierda
        p = lbw.getPathIterator(at);
        p.currentSegment(coord);

        x = coord[0];
        y = coord[1];

        if (t.getSurface(0).contains(x, y)) {
            wheel[2] = true;
        }

        //Comprobamos rueda trasera derecha
        p = rbw.getPathIterator(at);
        p.currentSegment(coord);

        x = coord[0];
        y = coord[1];

        if (t.getSurface(0).contains(x, y)) {
            wheel[3] = true;
        }
    }
}
